/****************************************************************************
 *  _____       ______  _____
 * |_   _|     |  ____|/ ____|
 *   | |  _ __ | |__  | (___    Institute of Embedded Systems
 *   | | | '_ \|  __|  \___ \   Zürcher Hochschule für Angewandte
 *  _| |_| | | | |____ ____) |  Wissenschaften
 * |_____|_| |_|______|_____/   8401 Winterthur, Switzerland
 *
 ****************************************************************************
 *
 * @version $Rev: 146 $
 * @author  $Author: bacr $
 * @date    $Date: 2013-10-02 17:56:25 +0200 (mer., 02 oct. 2013) $
 *
 ***************************************************************************/

#ifndef __ETHERNET_PACKET_H__
#define __ETHERNET_PACKET_H__

typedef struct vlan_header_t     vlan_header_t;
typedef struct ethernet_header_t ethernet_header_t;
typedef struct ethernet_packet_t ethernet_packet_t;

#include "object.h"

#define ETHERNET_PACKET(obj) ((ethernet_packet_t *) obj)

/* length on the wire! */
#define ETHERNET_PACKET_LEN             14
#define VLAN_PACKET_LEN                 18

#define ETHERNET_PACKET_OFFSET_DEST     0
#define ETHERNET_PACKET_OFFSET_SRC      6
#define ETHERNET_PACKET_OFFSET_TYPE     12
#define VLAN_PACKET_OFFSET_VLAN         14
#define VLAN_PACKET_OFFSET_TYPE         16

#define MAC_ADDRESS_LEN                 6

#define ETHERTYPE_IPV4                  0x0800
#define ETHERTYPE_IPV6                  0x86DD
#define ETHERTYPE_ARP                   0x0806
#define ETHERTYPE_VLAN                  0x8100
#define ETHERTYPE_PTP2                  0x88F7

#define ALIGNED

struct vlan_header_t {
    union {
        uint16_t        raw;
        struct {
            uint16_t    vid : 12;
            uint16_t    cfi : 1;
            uint16_t    pcp : 3;
        };
    };
    uint16_t            type;
};

/* network byte order */
#define ETHERNET_HEADER         \
    mac_address_t       dest;   \
    mac_address_t       src;    \
    uint16_t            type;   \
    vlan_header_t       vlan;

/**
 * @struct ethernet_header_t
 * @brief  Ethernet header
 * @see    ethernet_packet_t
 *
 * @var    ethernet_header_t::dest
 * @brief  Destination MAC-address
 *
 * @var    ethernet_header_t::src
 * @brief  Source MAC-address
 *
 * @var    ethernet_header_t::type
 * @brief  Ethertype (ex. IP=0x0800, VLAN=0x8100)
 */
struct ethernet_header_t {
    ETHERNET_HEADER
};

/**
 * @struct ethernet_packet_t
 * @brief  Ethernet packet
 * @see    ethernet_header_t
 */
struct ethernet_packet_t {
    object_t            obj;
    info_header_t       info;
    ETHERNET_HEADER
};

uint32_t    ethernet_packet_encode(ethernet_packet_t *this, raw_packet_t *raw_packet);
void        ethernet_packet_decode(ethernet_packet_t *this, raw_packet_t *raw_packet);

#endif

